<?php

class Benservi_Boleto_Santander{
     
     public $dadosboleto = array();
     public $codigo_banco_com_dv;

     public function init(){}

     public function factory()
     {
        $codigobanco = "033"; //Antigamente era 353
        $codigo_banco_com_dv = $this->geraCodigoBanco($codigobanco);
        $this->codigo_banco_com_dv = $codigo_banco_com_dv;
        $nummoeda = "9";
        $fixo     = "9";   
        $ios	  = "0";   
        
        // ---------------------- FIM CONFIGURAÇÃO DO SEU BOLETO --------------- //

        $fator_vencimento = $this->fator_vencimento($this->dadosboleto["data_vencimento"]);

        //valor tem 10 digitos, sem virgula
        $valor = $this->formata_numero($this->dadosboleto["valor_boleto"],10,0,"valor");
        //Modalidade Carteira
        $carteira = $this->dadosboleto["carteira"];
        //codigocedente deve possuir 7 caracteres
        $codigocliente = $this->formata_numero($this->dadosboleto["codigo_cliente"],7,0);

        //nosso número (sem dv) é 11 digitos
        $nnum = $this->formata_numero($this->dadosboleto["nosso_numero"],7,0);

        //dv do nosso número
        $dv_nosso_numero = $this->modulo_11($nnum,9,0);       
        
        $nossonumero = "00000".$nnum.$dv_nosso_numero;

        $vencimento = $this->dadosboleto["data_vencimento"];

        $vencjuliano = $this->dataJuliano($vencimento);
        
        $barra = "$codigobanco$nummoeda$fator_vencimento$valor$fixo$codigocliente$nossonumero$ios$carteira";
        $barraAux = "$codigobanco - $nummoeda - $fator_vencimento - $valor - $fixo - $codigocliente - $nossonumero - $ios - $carteira";
       
               
        $dv = $this->digitoVerificador_barra($barra);
        
        $linha = substr($barra,0,4) . $dv . substr($barra,4);
                
        $this->dadosboleto["codigo_barras"] = $linha;
        $this->dadosboleto["linha_digitavel"] = $this->monta_linha_digitavel($linha);
       
        //$this->codigo_barra = $linha;

        $this->dadosboleto["nosso_numero"] = $nossonumero;
        $this->dadosboleto["codigo_banco_com_dv"] = $codigo_banco_com_dv;

        return $this->dadosboleto["linha_digitavel"];
     }  

    private function dataJuliano($data)
    {
            $dia = (int)substr($data,1,2);
            $mes = (int)substr($data,3,2);
            $ano = (int)substr($data,6,4);
            $dataf = strtotime("$ano/$mes/$dia");
            $datai = strtotime(($ano-1).'/12/31');
            $dias  = (int)(($dataf - $datai)/(60*60*24));
      return str_pad($dias,3,'0',STR_PAD_LEFT).substr($data,9,4);
    }

    private function digitoVerificador_nossonumero($numero) {
            $resto2 = modulo_11($numero, 9, 1);
         $digito = 11 - $resto2;
         if ($digito == 10 || $digito == 11) {
            $dv = 0;
         } else {
            $dv = $digito;
         }
             return $dv;
    }


    private function digitoVerificador_barra($numero) {
            $resto2 = $this->modulo_11($numero, 9, 1);
         if ($resto2 == 0 || $resto2 == 1 || $resto2 == 10) {
            $dv = 1;
         } else {
                    $dv = 11 - $resto2;
         }
             return $dv;
    }

    private function formata_numero($numero,$loop,$insert,$tipo = "geral") {
	if ($tipo == "geral") {
		$numero = str_replace(",","",$numero);
		while(strlen($numero)<$loop){
			$numero = $insert . $numero;
		}
	}
	if ($tipo == "valor") {
		/*
		retira as virgulas
		formata o numero
		preenche com zeros
		*/
		$numero = str_replace(",","",$numero);
		while(strlen($numero)<$loop){
			$numero = $insert . $numero;
		}
	}
	if ($tipo == "convenio") {
		while(strlen($numero)<$loop){
			$numero = $numero . $insert;
		}
	}
	return $numero;
    }


    private function esquerda($entra,$comp){
            return substr($entra,0,$comp);
    }

    private function direita($entra,$comp){
            return substr($entra,strlen($entra)-$comp,$comp);
    }

    private function fator_vencimento($data) {
            $data = explode("/",$data);
            $ano = $data[2];
            $mes = $data[1];
            $dia = $data[0];
        return(abs(($this->_dateToDays("1997","10","07")) - ($this->_dateToDays($ano, $mes, $dia))));
    }

    private function _dateToDays($year,$month,$day) {
        $century = substr($year, 0, 2);
        $year = substr($year, 2, 2);
        if ($month > 2) {
            $month -= 3;
        } else {
            $month += 9;
            if ($year) {
                $year--;
            } else {
                $year = 99;
                $century --;
            }
        }
        return ( floor((  146097 * $century)    /  4 ) +
                floor(( 1461 * $year)        /  4 ) +
                floor(( 153 * $month +  2) /  5 ) +
                    $day +  1721119);
    }

        public function modulo_10($num) {
                        $numtotal10 = 0;
                $fator = 2;

                // Separacao dos numeros
                for ($i = strlen($num); $i > 0; $i--) {
                    // pega cada numero isoladamente
                    $numeros[$i] = substr($num,$i-1,1);
                    // Efetua multiplicacao do numero pelo (falor 10)
                    // 2002-07-07 01:33:34 Macete para adequar ao Mod10 do Itaú
                    $temp = $numeros[$i] * $fator;
                    $temp0=0;
                    foreach (preg_split('//',$temp,-1,PREG_SPLIT_NO_EMPTY) as $k=>$v){ $temp0+=$v; }
                    $parcial10[$i] = $temp0; //$numeros[$i] * $fator;
                    // monta sequencia para soma dos digitos no (modulo 10)
                    $numtotal10 += $parcial10[$i];
                    if ($fator == 2) {
                        $fator = 1;
                    } else {
                        $fator = 2; // intercala fator de multiplicacao (modulo 10)
                    }
                }

                // várias linhas removidas, vide função original
                // Calculo do modulo 10
                $resto = $numtotal10 % 10;
                $digito = 10 - $resto;
                if ($resto == 0) {
                    $digito = 0;
                }

                return $digito;

        }

    protected function modulo_11($num, $base=9, $r=0)  {
        /**
         *   Autor:
         *           Pablo Costa <pablo@users.sourceforge.net>
         *
         *   Função:
         *    Calculo do Modulo 11 para geracao do digito verificador
         *    de boletos bancarios conforme documentos obtidos
         *    da Febraban - www.febraban.org.br
         *
         *   Entrada:
         *     $num: string numérica para a qual se deseja calcularo digito verificador;
         *     $base: valor maximo de multiplicacao [2-$base]
         *     $r: quando especificado um devolve somente o resto
         *
         *   Saída:
         *     Retorna o Digito verificador.
         *
         *   Observações:
         *     - Script desenvolvido sem nenhum reaproveitamento de código pré existente.
         *     - Assume-se que a verificação do formato das variáveis de entrada é feita antes da execução deste script.
         */

        $soma = 0;
        $fator = 2;

        /* Separacao dos numeros */
        for ($i = strlen($num); $i > 0; $i--) {
            // pega cada numero isoladamente
            $numeros[$i] = substr($num,$i-1,1);
            // Efetua multiplicacao do numero pelo falor
            $parcial[$i] = $numeros[$i] * $fator;
            // Soma dos digitos
            $soma += $parcial[$i];
            if ($fator == $base) {
                // restaura fator de multiplicacao para 2
                $fator = 1;
            }
            $fator++;
        }

        /* Calculo do modulo 11 */
        if ($r == 0) {
            $soma *= 10;
            $digito = $soma % 11;
            if ($digito == 10) {
                $digito = 0;
            }
            return $digito;
        } elseif ($r == 1){
            $resto = $soma % 11;
            return $resto;
        }
    }

    private function modulo_11_invertido($num)
    {
       $ftini = 2;
       $fator = $ftfim = 9;
       $soma = 0;

       for ($i = strlen($num); $i > 0; $i--)
       {
              $soma += substr($num,$i-1,1) * $fator;
              if(--$fator < $ftini)
                 $fator = $ftfim;
       }

        $digito = $soma % 11;

            if($digito > 9)
               $digito = 0;

            return $digito;
    }

    private function monta_linha_digitavel($codigo)
    {

            $codigo = $codigo;            
            // Posição 	Conteúdo
            // 1 a 3    Número do banco
            // 4        Código da Moeda - 9 para Real ou 8 - outras moedas
            // 5        Fixo "9'
            // 6 a 9    PSK - codigo cliente (4 primeiros digitos)
            // 10 a 12  Restante do PSK (3 digitos)
            // 13 a 19  7 primeiros digitos do Nosso Numero
            // 20 a 25  Restante do Nosso numero (8 digitos) - total 13 (incluindo digito verificador)
            // 26 a 26  IOS
            // 27 a 29  Tipo Modalidade Carteira
            // 30 a 30  Dígito verificador do código de barras
            // 31 a 34  Fator de vencimento (qtdade de dias desde 07/10/1997 até a data de vencimento)
            // 35 a 44  Valor do título

            // 1. Primeiro Grupo - composto pelo código do banco, código da moéda, Valor Fixo "9"
            // e 4 primeiros digitos do PSK (codigo do cliente) e DV (modulo10) deste campo
            $campo1 = substr($codigo,0,3) . substr($codigo,3,1) . substr($codigo,19,1) . substr($codigo,20,4);
            $campo1 = $campo1 . $this->modulo_10($campo1);
            $campo1 = substr($campo1, 0, 5).'.'.substr($campo1, 5);



            // 2. Segundo Grupo - composto pelas 3 últimas posiçoes do PSK e 7 primeiros dígitos do Nosso Número
            // e DV (modulo10) deste campo
            $campo2 = substr($codigo,24,10);
            $campo2 = $campo2 . $this->modulo_10($campo2);
            $campo2 = substr($campo2, 0, 5).'.'.substr($campo2, 5);


	// 3. Terceiro Grupo - Composto por : Restante do Nosso Numero (6 digitos), IOS, Modalidade da Carteira
	// e DV (modulo10) deste campo
	    $campo3 = substr($codigo,34,10);
	    $teste = $campo3;
            $campo3 = $campo3 . $this->modulo_10($campo3);
            $campo3 = substr($campo3, 0, 5).'.'.substr($campo3, 5);

            // 4. Campo - digito verificador do codigo de barras
            $campo4 = substr($codigo, 4, 1);

            // 5. Campo composto pelo fator vencimento e valor nominal do documento, sem
            // indicacao de zeros a esquerda e sem edicao (sem ponto e virgula). Quando se
            // tratar de valor zerado, a representacao deve ser 0000000000 (dez zeros).
            $campo5 = substr($codigo, 5, 4) . substr($codigo, 9, 10);

            return "$campo1 $campo2 $campo3 $campo4 $campo5";	            
    }

    private function geraCodigoBanco($numero) {
            $parte1 = substr($numero, 0, 3);
            $parte2 = $this->modulo_11($parte1);
            return $parte1 . "-" . $parte2;
    }
}

?>
